package test.base.medium;

import java.awt.Window.Type;
import java.lang.reflect.Field;
import java.util.EnumSet;

import javax.swing.JFrame;

import org.bytedeco.ffmpeg.avformat.AVFormatContext;
import org.bytedeco.ffmpeg.global.avcodec;
import org.bytedeco.ffmpeg.global.avutil;
import org.bytedeco.javacv.CanvasFrame;
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.FFmpegFrameRecorder;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.FrameRecorder;
import org.bytedeco.javacv.OpenCVFrameConverter;
import org.bytedeco.opencv.opencv_core.IplImage;

public class javacvRtsptest2 {
	static boolean exit = false;

	/**
	 * 
	 * @param rtspPath
	 * @param rtmpPath
	 * @param 是否录制音频    （0:不录制/1:录制）
	 * @param saveVideo
	 * @throws Exception
	 */
	public static void rtsp2rtmp(String rtspPath, String rtmpPath, int 是否录制音频, boolean 是否保存视频) {
		// 使用rtsp的时候需要使用 FFmpegFrameGrabber，不能再用 FrameGrabber
		// int width = 640, height = 480;
		FFmpegFrameGrabber grabber;
		try {
			grabber = FFmpegFrameGrabber.createDefault(rtspPath);
			grabber.setOption("rtsp_transport", "tcp"); // 使用tcp的方式，不然会丢包很严重
			// grabber.setPixelFormat(avutil.AV_PIX_FMT_YUV420P);
			// grabber.setImageWidth(width);
			// grabber.setImageHeight(height);
			// grabber.setFrameRate(25);
			grabber.setPixelFormat(avutil.AV_PIX_FMT_YUVJ420P);
			System.out.println("grabber start");
			grabber.start();

			// 流媒体输出地址，分辨率（长，高），是否录制音频（0:不录制/1:录制）

			OpenCVFrameConverter.ToIplImage conveter = new OpenCVFrameConverter.ToIplImage();
			Frame grabframe = grabber.grab();
			IplImage grabbedImage = null;
			if (grabframe != null) {
				System.out.println("取到第一帧");
				grabbedImage = conveter.convert(grabframe);
			} else {
				System.out.println("没有取到第一帧");
			}
			// 如果想要保存图片,可以使用 opencv_imgcodecs.cvSaveImage("hello.jpg", grabbedImage);来保存图片

			FrameRecorder recorder=null;
			int width = grabber.getImageWidth() / 2;
			int height = grabber.getImageHeight() / 2;
			try {
				recorder = FrameRecorder.createDefault(rtmpPath, width, height);
			} catch (org.bytedeco.javacv.FrameRecorder.Exception e) {
				e.printStackTrace();
				return;
			}

			recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264); // avcodec.AV_CODEC_ID_H264
			recorder.setFormat("flv");
			recorder.setFrameRate(18);
			recorder.setGopSize(18);

			try {
				recorder.start();
			} catch (org.bytedeco.javacv.FrameRecorder.Exception e) {
				e.printStackTrace();
				return;

			}

			int count = 0;
			// grabber.flush();

			final CanvasFrame cFrame = new CanvasFrame("frame");
			cFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
			cFrame.setAlwaysOnTop(true);

			Frame capturedFrame = null;

			// 有些时候，程序执行回报下列错误，添加一行代码解决此问题
			// av_interleaved_write_frame() error -22 while writing interleaved video
			// packet.
			grabber.flush();
			try {
			while ((capturedFrame = grabber.grab()) != null) {
				if (cFrame.isVisible()) {
					// EnumSet<Type> videoOrAudio= cFrame.getType();

					cFrame.showImage(capturedFrame);
				}
				// System.out.println(grabber.getFrameNumber()+ "--" +capturedFrame.timestamp);
				// recorder.setTimestamp(capturedFrame.timestamp);
				
					recorder.record(capturedFrame);
				
			}
			} catch (org.bytedeco.javacv.FrameRecorder.Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			cFrame.dispose();

			grabber.stop();
			grabber.release();
			recorder.stop();
			recorder.release();

			// cFrame.dispose();
			// recorder.close();
			grabber.close();
		} catch (org.bytedeco.javacv.FrameGrabber.Exception | org.bytedeco.javacv.FrameRecorder.Exception e) {

			e.printStackTrace();

		}
		//
	}

	public static void rtsp2rtmp(String rtspPath, String rtmpPath) throws Exception {
		final int captureWidth = 640;
		final int captureHeight = 360;
		final FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(rtspPath);
		// grabber.setImageWidth(captureWidth);
		// grabber.setImageHeight(captureHeight);
		// rtsp格式一般添加TCP配置，否则丢帧会比较严重
		// Brick在测试过程发现，该参数改成udp可以解决部分电脑出现的下列报警，但是丢帧比较严重
		// av_interleaved_write_frame() error -22 while writing interleaved video
		// packet.
		grabber.setOption("rtsp_transport", "tcp");

		grabber.start();
		// 最后一个参数是AudioChannels，建议通过grabber获取
		// 流媒体输出地址，分辨率（长，高），是否录制音频（0:不录制/1:录制）
		final FFmpegFrameRecorder recorder = new FFmpegFrameRecorder(rtmpPath, captureWidth, captureHeight, 1);
		recorder.setInterleaved(true);
		// 降低编码延时
		// recorder.setVideoOption("tune", "zerolatency");
		// 提升编码速度
		// recorder.setVideoOption("preset", "ultrafast");
		// 视频质量参数(详见 https://trac.ffmpeg.org/wiki/Encode/H.264)
		// recorder.setVideoOption("crf", "28");
		// 分辨率
		// recorder.setVideoBitrate(2000000);

		// recorder.setPixelFormat(0); // yuv420p 图像分辨率
		// 视频编码格式
		recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264);
		// 设置像素格式
		recorder.setPixelFormat(avutil.AV_PIX_FMT_YUV420P);
		// 视频格式 // rtmp的类型
		recorder.setFormat("flv");
		// 视频帧率
		recorder.setFrameRate(15);
		// recorder.setGopSize(60);
		recorder.setAudioOption("crf", "0");
		// recorder.setAudioQuality(0);
		// recorder.setAudioBitrate(192000);
		// recorder.setSampleRate(44100);
		// 建议从grabber获取AudioChannels
		// recorder.setAudioChannels(1);
		// recorder.setAudioCodec(avcodec.AV_CODEC_ID_AAC);
		recorder.start();

		// 解决音视频同步导致的延时问题
		Field field = recorder.getClass().getDeclaredField("oc");
		field.setAccessible(true);
		// AVFormatContext描述了一个媒体文件或媒体流的构成和基本信息，位于avformat.h文件中。
		AVFormatContext oc = (AVFormatContext) field.get(recorder);
		oc.max_interleave_delta(100);

		// 用来测试的frame窗口
		final CanvasFrame cFrame = new CanvasFrame("frame");
		Frame capturedFrame = null;

		// 有些时候，程序执行回报下列错误，添加一行代码解决此问题
		// av_interleaved_write_frame() error -22 while writing interleaved video
		// packet.
		grabber.flush();

		while ((capturedFrame = grabber.grab()) != null) {
			if (cFrame.isVisible()) {
				cFrame.showImage(capturedFrame);
			}
			// System.out.println(grabber.getFrameNumber()+ "--" +capturedFrame.timestamp);
			// recorder.setTimestamp(capturedFrame.timestamp);
			// recorder.record(capturedFrame);
		}
		cFrame.dispose();
		recorder.close();
		grabber.close();
	}
}
